import { combineReducers } from 'redux';
import _ from 'lodash';

import {
	UPDATE_DATA,
	SET_INFO,
	UPDATE_NODES_COUNT,
	UPDATE_CURRENT_NODE_DETEAL,
	UPDATE_RELATIONSHIPS,
	REMOVE_NODE,
	UPDATE_RELATIONSHIPS_COUNT,
	MAKE_CONNECT,
	ADD_NODE,
	UPDATE_DETAIL,
	DEL_NODE,
	MARK_SELECTED,
	GET_DATASOURCE_LIST,
	CREATE_NODE,
	CREATE_INDEX,
	CREATE_RELATIONSHIP,
	GET_TOPOLOGY,
	SET_CURRENT_RELATION_EDITOR,
	GET_LIST_NODES,
	GET_NODE,
	GET_LIST_RELATIONSHIPS,
	GET_RELATION_BY_ID,
	CLEAR
} from './action';

function graphData(state={
	relationships: [], 
	nodes: [],
	info: {},
	currentNode: {},
	relationshipsCount: 0,
	nodesCount: 0,
	createdNodesList: [],
	dealNodes: [],
	dealRelations: [],
	dataSourcelist: [],
	relationshipList: [],
	currentId: null
}, action) {
	switch(action.type) {
		case UPDATE_DATA:
			return {...state, relationships: action.relationships, nodes: action.nodes, info: {}};
		case SET_INFO:
			return {...state, info: action.info};
		case UPDATE_NODES_COUNT:
			return {...state, nodesCount: action.nodesCount }
		case UPDATE_RELATIONSHIPS_COUNT:
			return {...state, relationshipsCount: action.relationshipsCount }
		case UPDATE_CURRENT_NODE_DETEAL:
			return {...state, currentNode: action.currentNode, nodes: action.nodes, relationships: [], info: {}}
		case UPDATE_RELATIONSHIPS:
			return {
				...state,
				relationships: _.uniqBy([
					...state.relationships,
					...action.relationships
				], 'id'),
				nodes: _.uniqBy([
					...state.nodes,
					...action.nodes
				], 'id'),
				info: {}
			}
		case SET_CURRENT_RELATION_EDITOR: {
			const {record} = action;
			return {
				...state,
				dealNodes: record.extra.dealNodes,
				dealRelations: record.extra.dealRelations
			}
		}
		case CLEAR: {
			return {
				...state,
				dealRelations: [],
				dealNodes: []
			}
		}
		case REMOVE_NODE:
			const finalNodes = state.nodes.filter(item => item.id !== action.nodeId);
			const finalRelationships = state.relationships.reduce((pre, item, index) => {
				if (item.startNode === action.nodeId || item.endNode === action.nodeId) {
					return pre;
				} else {
					return [...pre, item]
				}
			}, [])
			return {
				...state,
				relationships: finalRelationships,
				nodes: finalNodes
			}
		case ADD_NODE:
			return {
				...state,
				dealNodes: [...state.dealNodes, action.value]
			}
		case CREATE_RELATIONSHIP: {
			const {testCreateRelationResult} = action;
			return {
				...state,
				relationshipList: [...state.relationshipList, testCreateRelationResult],
				dealNodes: [],
				dealRelations: []
			}
		}
		case GET_RELATION_BY_ID: {
			const {currentRelation} = action;
			console.log('currentRelation: ', currentRelation);
			return {
				...state,
				dealNodes: currentRelation.extra.dealNodes,
				dealRelations: currentRelation.extra.dealRelations
			}
		}
		case GET_LIST_RELATIONSHIPS: {
			return {
				...state,
				relationshipList: action.relationshipList
			}
		}
		case DEL_NODE: {
			const index = state.dealNodes.findIndex(item => item.id == action.id);
			const affectedDealRelations = state.dealRelations.reduce((pre, item, index) => {
				const associateNode = item.associateNode;
				if (associateNode[0].id != action.id && associateNode[1].id != action.id) {
					return [...pre, item];
				} else {
					return pre;
				}
			}, []);
			return {
				...state,
				dealNodes: [
					...state.dealNodes.slice(0, index),
					...state.dealNodes.slice(index + 1)
				],
				dealRelations: affectedDealRelations
			}
		}
		case MAKE_CONNECT:
			return {
				...state,
				dealRelations: [...state.dealRelations, {associateNode: action.value, direction: 0, id: action.id}]
			}
		case UPDATE_DETAIL: {
			const {changeDetail, componentType} = action;
			let renderObj = componentType === 'node' ? state.dealNodes.find(item => item.selected) : state.dealRelations.find(item => item.selected);
			let index = componentType === 'node' ? state.dealNodes.findIndex(item => item.selected) : state.dealRelations.findIndex(item => item.selected);
			if (typeof changeDetail === 'object') {
				if (changeDetail.key === 'label') {
					const selectedNode = state.createdNodesList.find(item => item.label == changeDetail.value);
					renderObj.columns = selectedNode.columns;
				}
				renderObj[changeDetail.key] = changeDetail.value;
			} else {
				//to do
			}
			return {
				...state,
				dealNodes: componentType === 'node' ? [
					...state.dealNodes.slice(0, index),
					renderObj,
					...state.dealNodes.slice(index + 1)
				] : state.dealNodes,
				dealRelations: componentType === 'node' ? state.dealRelations : [
					...state.dealRelations.slice(0, index),
					renderObj,
					...state.dealRelations.slice(index + 1)
				]
			}
		}
		case MARK_SELECTED: {
			const { id, handleType } = action;
			let finalNodes = [], finalRelationships = [];
			if (handleType == 'clear') {
				finalNodes = state.dealNodes.map(item => {
					if (item.selected) {
						delete item.selected;
					}
					return item;
				});
				finalRelationships = state.dealRelations.map(item => {
					if (item.selected) {
						delete item.selected;
					}
					return item;
				});
				return {
					...state,
					dealRelations: finalRelationships.slice(0),
					dealNodes: finalNodes.slice(0),
					currentId: null
				}
			} else if (handleType == 'node') {
				const index = state.dealNodes.findIndex(item => item.id == id);
				return {
					...state,
					dealNodes: [
						...state.dealNodes.slice(0, index),
						Object.assign(state.dealNodes[index], {selected: true}),
						...state.dealNodes.slice(index + 1)
					],
					currentId: id
				}
			} else if (handleType == 'relation') {
				const index = state.dealRelations.findIndex(item => item.id == id);
				return {
					...state,
					dealRelations: [
						...state.dealRelations.slice(0, index),
						Object.assign(state.dealRelations[index], {selected: true}),
						...state.dealRelations.slice(index + 1)
					],
					currentId: id
				}
			}
		}
		case GET_DATASOURCE_LIST: {
			return {
				...state,
				dataSourcelist: action.dataSourcelist
			}
		}
		case CREATE_NODE: {
			return {
				...state,
				createdNodesList: [
					...state.createdNodesList,
					action.testCreateNodeResult
				]
			}
		}
		case GET_LIST_NODES: {
			return {
				...state,
				createdNodesList: action.createdNodesList
			}
		}
		case GET_NODE: {
			const {currentNode} = action;
			console.log('currentNode: ', currentNode);
			const index = state.createdNodesList.findIndex(item => item.id === currentNode.id);
			return {
				...state,
				currentNode: currentNode,
				createdNodesList: state.createdNodesList.length ? [
					...state.createdNodesList.slice(0, index),
					Object.assign(state.createdNodesList[index], {columns: currentNode.props}),
					...state.createdNodesList.slice(index + 1)
				] : state.createdNodesList
			}
		}
		case CREATE_INDEX: {
			return {
				...state
			}
		}
		case GET_TOPOLOGY: {
			return state;
		}
		default:
			return state;
	}
}

export default combineReducers({
	graphData,
});